﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;      //添加串口类引用库
namespace VSSerialPort
{
    public partial class Form1 : Form
    {
        //添加你的变量
        int m_bConnected;       //串口连接标志位
        String[] FindSerialPortsRes;        //存储搜索到的串口号
        long m_longReceiveNum;      //已接收字符数
        long m_longSendNum;         //已发送字符数
        int m_bSendMode;            //发送模式
        int m_bReceiveMode;         //接收模式
        String m_strDataReceive;    //收到的数据
        public Form1()
        {
            InitializeComponent();
        }
        /*
         * 默认的构造函数会在设计完窗体之后，用于呈现窗口布局，
         * 是在Load之前执行。通常这个过程是不会让窗体使用其它资源，比如数据。
         * 而Load事件，在第一个显示窗体前发生，
         * 窗体显示前可以进行很多操作，比如加载默认数据；
         * 执行一个方法；为一个变量赋值等等。
         * Load函数相当于你的初始化函数
         */
        private void Form1_Load(object sender, EventArgs e)
        {
            ParaInit();
            ControlInit();
            radioButton1.Checked = true;
        }
        private void ControlInit()      //控件初始化
        {
            GetSPNames();               //初始化串口名称下拉菜单
           // GetSPBaudRate();            //初始化串口波特率下拉菜单
           // radioButton_HexSend.Checked = true;         //单选按钮初始化
            //radioButton__HexReceive.Checked = true;
        }
        private void ParaInit()         //参数初始化
        {
            m_bConnected = 0;           //初始化标志位
            FindSerialPortsRes = null;      //初始化数组
            m_longReceiveNum = 0;       //初始化接收数据数
            m_longSendNum = 0;          //初始化发送数据数
            m_bReceiveMode = 0;         //接收模式，0为HEX，1为CHAR
            m_bSendMode = 0;            //发送模式
            m_strDataReceive = "";      //初始化接收数据字符串
        }

        private string[] GetSPNames()       //获取所有串口并存入下拉列表
        {
            String[] FindSerialPortsRes = null;                              //清空存储串口名称的数组
            FindSerialPortsRes = SerialPort.GetPortNames();         //获取所有串口名称
            return FindSerialPortsRes;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (comboBox1.Text == "")
            {
                MessageBox.Show("没有串口", "error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Com_flash();
                return;
            }


            serialPort1.BaudRate = int.Parse(comboBox2.Text);     //从串口波特率的下拉菜单获取字符串波特率并转为int型
            serialPort1.PortName = comboBox1.Text;    //串口号从下拉菜单的选中值中获取
            serialPort1.DataBits = 8;                       //数据位8位
            serialPort1.StopBits = StopBits.One;            //停止位1位
            serialPort1.Parity = Parity.None;               //校验位无
            serialPort1.Encoding = Encoding.Default;        //编码方式，默认的就是16进制数据

            serialPort1.Open();

            if (serialPort1.IsOpen)
            {
                button1.Enabled = false;
                button2.Enabled = true;
            }
  
 

        }
        //刷新串口
        private void Com_flash()
        {
            String[] FindSerialPortsRes = GetSPNames();//扫描串口
            if (FindSerialPortsRes.Length != 0)//至少有一个 那就把第一个表现吧
            {
                comboBox1.Text = FindSerialPortsRes[0];
                for (int i = 1; i < FindSerialPortsRes.Length; i++)//其他的放在列表中
                    comboBox1.Items.Add(FindSerialPortsRes[i]);
            }
            else
                comboBox1.Text = "";

        }
        //双击周围的框框 出现这个函数 init 是初始化框框的
        private void Form1_Load_1(object sender, EventArgs e)
        {
            radioButton2.Checked = true;
            comboBox2.Text = "115200";
            Com_flash();//刷新串口 给box做准备
            button2.Enabled = false;         
            sendstr.Checked = true;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen) //如果串口打开则进行关闭，否则返回
            {
                serialPort1.Close();    //关闭串口
                button1.Enabled = true;
                button2.Enabled = false;

            }
        }
        public static byte GetHexBitsValue(byte ch)
        {
            byte sz = 0;
            if (ch <= '9' && ch >= '0')
                sz = (byte)(ch - 0x30);
            if (ch <= 'F' && ch >= 'A')
                sz = (byte)(ch - 0x37);
            if (ch <= 'f' && ch >= 'a')
                sz = (byte)(ch - 0x57);

            return sz;
        }
        public static byte[] ToDigitsBytes(string theHex)
        {
            byte[] bytes = new byte[theHex.Length / 2 + (((theHex.Length % 2) > 0) ? 1 : 0)];
            for (int i = 0; i < bytes.Length; i++)
            {
                char lowbits = theHex[i * 2];
                char highbits;

                if ((i * 2 + 1) < theHex.Length)
                    highbits = theHex[i * 2 + 1];
                else
                    highbits = '0';

                int a = (int)GetHexBitsValue((byte)lowbits);
                int b = (int)GetHexBitsValue((byte)highbits);
                bytes[i] = (byte)((a << 4) + b);
            }

            return bytes;
        }
        private void button3_Click(object sender, EventArgs e)
        {
            Com_send(textBox1.Text, sendstr.Checked);
        }

        private void Com_send(string msg,bool type)
        {
            if (msg == "") { MessageBox.Show("发送为空", "error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; }
            if (!serialPort1.IsOpen) { MessageBox.Show("串口没开", "error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; }

            if (type == true)
                serialPort1.Write(msg);//直接发送string
            else
            {
                int len = msg.Length / 2;
                byte[] HexArry = new byte[len];
                HexArry = ToDigitsBytes(msg);
                serialPort1.Write(HexArry, 0, len);  //发送
            }



          //  richTextBox1.Text = serialPort1.ReadExisting();
        }

        private void button4_Click(object sender, EventArgs e)
        {
            Com_send(textBox2.Text, sendstr.Checked);
        }

        private void button5_Click(object sender, EventArgs e)
        {
            richTextBox1.Text = "";
        }

        //组件--属性 写一个触发函数
        private void ComReceived(object sender, SerialDataReceivedEventArgs e)
        {
            //从线程的资源 在 主线程调用 失败
            //https://mp.weixin.qq.com/s/GjINwgnftS6RU-BVJh8mbA
            // m_strDataReceive = serialPort1.ReadExisting();
            // richTextBox1.Text += m_strDataReceive;
            AppendTextBox(serialPort1.ReadExisting());

        }
        delegate void SetTextCallback(string text);

        private void AppendTextBox(string text)
        {
            if (richTextBox1.InvokeRequired)   //文本框 如果被子线程调用
            {
                SetTextCallback d = new SetTextCallback(AppendTextBox);     //回调AppendTextBox这个函数
                this.Invoke(d, text);               //交给主线程
            }
            else
            {
                if (radioButton1.Checked)//string 发送
                {
                    richTextBox1.SuspendLayout();
                    richTextBox1.Text += text;
                    richTextBox1.ResumeLayout(false);
                }
                else
                {
                    //转为16进制显示
                    char[] TempChar = text.ToCharArray(0, text.Length);
                    int high = 0;
                    int low = 0;
                    char charTemp = 'a';
                    for (int i = 0; i < text.Length; i++)
                    {
                        high = (TempChar[i]) / 16;
                        low = (TempChar[i]) % 16;
                        if (high <= 9)
                            richTextBox1.Text += high.ToString();
                        else
                            richTextBox1.Text += (charTemp + (high - 9)).ToString();
                        if (low <= 9)
                            richTextBox1.Text += low.ToString();
                        else
                            richTextBox1.Text += (charTemp + (low - 9)).ToString();
                        richTextBox1.Text += " ";  //加个空格
                    }
                }
            }
        }

    }
}
